package cn.netswap.jeegorilla.framework.scheduler.quartz;


import cn.netswap.jeegorilla.entity.jpa.BaseQuartzConfig;
import cn.netswap.jeegorilla.framework.scheduler.bean.ScheduleEnum;
import cn.netswap.jeegorilla.service.jpa.BaseQuartzConfigJpaService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;


import java.util.List;

/**
 * Created by lai_gw on 2020/3/15.
 */
@Service
public class GorillaSchedulerFactory {

    Logger log = LoggerFactory.getLogger(GorillaSchedulerFactory.class);

    @Autowired
    SchedulerFactoryBean schedulerFactoryBean;

    /**
     * 任务配置读取服务
     */
    @Autowired
    private BaseQuartzConfigJpaService baseQuartzConfigJpaService;

    public void scheduleJobs() throws SchedulerException {
        Scheduler scheduler = getScheduler();
        // 为了避免org.quartz.ObjectAlreadyExistsException，在执行前将scheduler进行清理
        scheduler.clear();
        startJob(scheduler);
    }

    /**
     * 获取scheduler
     * @return
     * @author pangxianhe
     */
    private Scheduler getScheduler() {
        return schedulerFactoryBean.getScheduler();
    }


    private void startJob(Scheduler scheduler) {
        try {
            List<BaseQuartzConfig> jobList = baseQuartzConfigJpaService.findAll();
            for (BaseQuartzConfig config : jobList) {
                String identity = config.getId() +"_"+ config.getQuartaName()+ config.getQuartaGroup();
                try {
                    // 0-暂停的任务 1-正常运行任务
                    if (1l != config.getState()) {
                        continue;
                    }
                   if(config.getTaskType().equals(ScheduleEnum.SIMPLE.name())){
                        this.dealSimpleOnceJobByStartTime(scheduler,config,identity);
                   }else if(config.getTaskType().equals(ScheduleEnum.CRON.name())){
                       this.dealCronJob(scheduler,config,identity);
                   }
                } catch (Exception e) {
                    log.info("定时启动异常：" + config.getQuartaName() + " 异常信息：" + e.getMessage());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理表达式任务
     * @param scheduler
     * @param config
     * @param identity
     * @throws ClassNotFoundException
     * @throws SchedulerException
     */
    private void dealCronJob(Scheduler scheduler, BaseQuartzConfig config, String identity) throws ClassNotFoundException, SchedulerException  {
        String classz = config.getQuartzClass();
        if (StringUtils.isNotBlank(classz)) {
            Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(classz);
            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(identity).build();
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(config.getExpression());
            CronTrigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(identity)
                    .withSchedule(scheduleBuilder)
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
        }
    }

    /**
     * 处理只执行一次的简便任务
     * @param scheduler
     * @param config
     * @param identity
     * @throws ClassNotFoundException
     * @throws SchedulerException
     */
    private void dealSimpleOnceJobByStartTime(Scheduler scheduler, BaseQuartzConfig config, String identity) throws ClassNotFoundException, SchedulerException {
        if(config.getTaskStartTime().getTime()>System.currentTimeMillis()){
            String classz = config.getQuartzClass();
            if (StringUtils.isNotBlank(classz)) {
                Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(classz);
                JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(identity).build();
                SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
                SimpleTrigger trigger = TriggerBuilder
                        .newTrigger()
                        .withIdentity(identity)
                        .startAt(config.getTaskStartTime())
                        .withSchedule(scheduleBuilder)
                        .build();
                scheduler.scheduleJob(jobDetail, trigger);
            }
        }
    }

    /**
     * 任务暂停
     */
    public void pauseJob(long id) throws Exception{
        Scheduler scheduler = getScheduler();
        BaseQuartzConfig config = baseQuartzConfigJpaService.getOne(id);
        String identity = config.getId() +"_"+ config.getQuartaName()+ config.getQuartaGroup();
        JobKey jobKey = JobKey.jobKey(identity);
        scheduler.deleteJob(jobKey);
    }

    /**
     * 任务恢复
     * @param id
     */
    public void resumeJob (long id) throws Exception {
        Scheduler scheduler = getScheduler();
        BaseQuartzConfig config = baseQuartzConfigJpaService.getOne(id);
        String identity = config.getId() +"_"+ config.getQuartaName()+ config.getQuartaGroup();

        if(config.getTaskType().equals(ScheduleEnum.SIMPLE.name())){
            dealSimpleResumeOnceSimpleJob(scheduler,config,identity);
        }else if(config.getTaskType().equals(ScheduleEnum.CRON.name())){
            dealCronResumeSimpleJob(scheduler,config,identity);
        }
    }

    private void dealCronResumeSimpleJob(Scheduler scheduler, BaseQuartzConfig config, String identity) throws ClassNotFoundException, SchedulerException {
        JobKey jobKey = JobKey.jobKey(identity);
        Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(config.getQuartzClass());
        JobDetail jobDetail1 = scheduler.getJobDetail(jobKey);
        if (jobDetail1 == null) {
            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(identity)
                    .build();
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(config.getExpression());
            CronTrigger trigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity(identity)
                    .withSchedule(scheduleBuilder)
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
        } else {
            scheduler.resumeJob(jobKey);
        }
    }

    private void dealSimpleResumeOnceSimpleJob(Scheduler scheduler, BaseQuartzConfig config, String identity) throws ClassNotFoundException, SchedulerException {
       if(config.getTaskStartTime().getTime()>System.currentTimeMillis()){
           JobKey jobKey = JobKey.jobKey(identity);
           Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(config.getQuartzClass());
           JobDetail jobDetail1 = scheduler.getJobDetail(jobKey);
           if (jobDetail1 == null) {
               JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(identity)
                       .build();
               SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
               SimpleTrigger trigger = TriggerBuilder
                       .newTrigger()
                       .withIdentity(identity)
                       .startAt(config.getTaskStartTime())
                       .withSchedule(scheduleBuilder)
                       .build();
               scheduler.scheduleJob(jobDetail, trigger);
           } else {
               scheduler.resumeJob(jobKey);
           }
       }
    }


}
